﻿using Microsoft.AspNetCore.SignalR;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Wicture.DbRESTFul;
using Wicture.EPC.OnlineQueryProxy.Agents;
using Wicture.EPC.OnlineQueryProxy.Proxy;

namespace Wicture.EPC.OnlineQueryProxy
{
    public class OnlineQueryServiceHub : Hub
    {
        private readonly IOnlineQueryResponseHandler _onlineQueryResponseHandler;
        private readonly IAgentManager _agentManager;

        public OnlineQueryServiceHub(IOnlineQueryResponseHandler onlineQueryResponseHandler, IAgentManager agentManager)
        {
            _onlineQueryResponseHandler = onlineQueryResponseHandler;
            _agentManager = agentManager;
        }

        /// <summary>
        /// Agent Join the hub or update its status.
        /// </summary>
        public async Task JoinOrUpdate(List<Agent> agents)
        {
            foreach (var agent in agents)
            {
                agent.ConnectionId = Context.ConnectionId;
                _agentManager.AddOrUpdate(agent);
                LoggerManager.Logger.LogInformation($"Agent: {agent.Name} - {agent.Id} was joined or updated.");
            }
            await Task.CompletedTask;
        }

        /// <summary>
        /// Send back query response by agent.
        /// </summary>
        public async Task SendQueryResponse(QueryResponse response)
        {
            LoggerManager.Logger.LogInformation($"Received queryResponse: {response.Params} from agent {response.AgentName}.");
            _onlineQueryResponseHandler.ProcessQueryResult(response);
            await Task.CompletedTask;
        }

        public override async Task OnDisconnectedAsync(Exception exception)
        {
            _agentManager.ForceOffline(Context.ConnectionId);

            LoggerManager.Logger.LogError(exception, "Client connected: " + Context.ConnectionId);

            await base.OnDisconnectedAsync(exception);
        }

        public override async Task OnConnectedAsync()
        {
            LoggerManager.Logger.LogInformation("Client reconnected: " + Context.ConnectionId);
            if (_agentManager.Reconnect(Context.ConnectionId) == true)
            {
                await Clients.Client(Context.ConnectionId).SendAsync("updateAgent");
            }
            else
            {
                await Clients.All.SendAsync("updateAgent");
            }

            await base.OnConnectedAsync();
        }
    }
}
